home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-03-10 | 68.6 KB | 2,610 lines |
- Newsgroups: comp.sources.unix
- From: jmsellens@watdragon.waterloo.edu (John M. Sellens)
- Subject: v25i151: msgd - sends a one line message to another user or users
- Sender: unix-sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: jmsellens@watdragon.waterloo.edu (John M. Sellens)
- Posting-Number: Volume 25, Issue 151
- Archive-Name: msgd
-
- [ name changed from msg to msgd to prevent name collision from volume 4.
- i'm rethinking the archive index to see whether such collisions are
- neccessary. --vix ]
-
- MSG sends a one line message to another user or users, possibly over
- the network. We like it much more than write(1) and talk(1).
-
- jmsellens@watdragon.waterloo.edu (John M. Sellens)
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: ./README ./Common ./Common/answerback.c ./Common/deliver.c
- # ./Common/errtext.c ./Common/misc.c ./Common/savemsg.c ./Include
- # ./Include/msg.h ./Include/msgoptions.h ./Makefile ./Man
- # ./Man/Makefile ./Man/mesg.1 ./Man/msg.1 ./Man/msgd.8 ./inetd.conf
- # ./mesg ./mesg/Makefile ./mesg/mesg.c ./msg ./msg/Makefile
- # ./msg/msg.c ./msg/remote.c ./msgd ./msgd/Makefile ./msgd/msgd.c
- # ./msgd/server.c ./services
- # Wrapped by jmsellen@watmath on Mon Mar 2 01:54:49 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f './README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./README'\"
- else
- echo shar: Extracting \"'./README'\" \(1625 characters\)
- sed "s/^X//" >'./README' <<'END_OF_FILE'
- XMSG sends a one line message to another user or users, possibly over
- Xthe network. We like it much more than write(1) and talk(1).
- X
- XFor example,
- X % msg jdoe@othermachine
- X Let's go eat!
- X %
- X jdoe@othermachine: ok - where?
- X msg -r
- X msg: Replying to 'jdoe@othermachine'
- X How about the cafeteria?
- X %
- X
- XTo install, add the lines to /etc/services and /etc/inetd.conf,
- Xmodify the Makefile and */Makefile to your needs, and adjust
- XInclude/msgoptions.h to set the options that are appropriate for you.
- X
- Xmesg is a modified version of the Berkeley mesg program. The Tahoe
- Xversion appears with the Berkeley copyright - this version is based on
- X4.2 or 4.3, and so I added the Berkeley copyright notice, and assume
- Xthat distribution is ok. This version allows you to set an answerback
- Xmessage that will be given to any user trying to send you a message.
- XNote that this version has to be setuid root so that it can remove
- Xother users answerback message files.
- X
- XWe use this on Sun3, Sun4, BSD Vax, Ultrix Vax, MIPS, DEC MIPS, and Sequent.
- X
- XNote that the service number that we use has not been officially
- Xregistered. If I ever get off my butt, and register a real number,
- Xit should be relatively easy to update things. Or so I like to think.
- XI'd like to encourage everyone to use the same port number i.e. 1241/tcp,
- Xotherwise we won't be able to talk to each other.
- X
- XNaturally, no warranties, bug fixes and enhancements accepted, but
- Xno support committments. Available via anonymous ftp from
- Xwatmath.waterloo.edu in pub/msg.shar.
- X
- XJohn Sellens
- XMath Faculty Computing Facility
- XUniversity of Waterloo
- Xjmsellens@watmath.waterloo.edu
- END_OF_FILE
- if test 1625 -ne `wc -c <'./README'`; then
- echo shar: \"'./README'\" unpacked with wrong size!
- fi
- # end of './README'
- fi
- if test ! -d './Common' ; then
- echo shar: Creating directory \"'./Common'\"
- mkdir './Common'
- fi
- if test -f './Common/answerback.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Common/answerback.c'\"
- else
- echo shar: Extracting \"'./Common/answerback.c'\" \(2095 characters\)
- sed "s/^X//" >'./Common/answerback.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /fsys4/usr/source/users/msg/Common/RCS/answerback.c,v 1.2 90/12/29 21:59:53 jmsellen Exp $";
- X#endif
- X
- X#if 0
- X/*
- X * $Log: answerback.c,v $
- X * Revision 1.2 90/12/29 21:59:53 jmsellen
- X * Use ANSBACK define from Include/msg.h
- X *
- X * Revision 1.1 87/08/06 19:06:19 sahayman
- X * Initial revision
- X *
- X */
- X#endif
- X
- X/* answerback.c
- X Return a user's answerback message to the person who sent him a
- X message.
- X*/
- X
- X#include "msg.h"
- X#include <pwd.h>
- X
- X#define MYBUFSIZ (BUFSIZ/2) /* BUFSIZ is max errmsg size */
- X
- X
- X/* We may be sending to multiple instances of the same user, so it makes
- X since to remember the last user we looked up and his/her UID to avoid
- X searching the passwd file again. */
- X
- Xanswerback( errcode, user, line )
- Xint errcode;
- Xchar *user;
- Xchar *line;
- X{
- X static char lastuser[25]; /* too hard to use sizeof() */
- X static int lastuid = -1;
- X struct stat sbuf;
- X FILE *fp;
- X char answerbuf[sizeof(ANSBACK)+25]; /* lots of extra room */
- X /* find name of answerback file */
- X (void) sprintf( answerbuf, "%s%s", ANSBACK, line );
- X /* Now make sure that if the answerback file exists, it belongs to
- X the user we're sending to */
- X if ( stat( answerbuf, &sbuf ) == -1 )
- X return; /* no answerback exists */
- X if ( strcmp( user, lastuser ) != 0 ) {
- X /* we don't know this guy, so look him up */
- X struct passwd *pw = getpwnam( user );
- X endpwent();
- X if ( pw == (struct passwd *)NULL )
- X /* I know this guy exists, but ignore it */
- X return;
- X (void) strcpy( lastuser, user );
- X lastuid = pw->pw_uid;
- X }
- X if ( sbuf.st_uid != lastuid )
- X return; /* not his file */
- X /* we don't care if we can't read his message - it's his problem */
- X if ( (fp=fopen(answerbuf,"r")) != FPNULL ) {
- X char buf[MYBUFSIZ+1];
- X int len;
- X if ( (len=fread( buf, 1, MYBUFSIZ, fp )) > 0 ) {
- X if ( buf[len-1] =='\n' ) len--;
- X buf[len] = '\0'; /* make it terminated */
- X if ( errcode == ANS_WARN )
- X errmsg( errcode, user, line, buf );
- X else
- X errmsg( errcode, user, hostname, line, buf );
- X }
- X (void) fclose( fp );
- X }
- X}
- END_OF_FILE
- if test 2095 -ne `wc -c <'./Common/answerback.c'`; then
- echo shar: \"'./Common/answerback.c'\" unpacked with wrong size!
- fi
- # end of './Common/answerback.c'
- fi
- if test -f './Common/deliver.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Common/deliver.c'\"
- else
- echo shar: Extracting \"'./Common/deliver.c'\" \(4264 characters\)
- sed "s/^X//" >'./Common/deliver.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /fsys4/usr/source/users/msg/Common/RCS/deliver.c,v 1.4 90/12/29 21:59:07 jmsellen Exp $";
- X#endif
- X
- X/* deliver.c
- X Deliver a message to a user on this machine.
- X*/
- X
- X/*
- X * Old revision log:
- X *
- X * Revision 1.4 87/06/04 12:49:47 jmsellens
- X * Changes to put the msg save file in /usr/tmp
- X * rationalized the code a little, added the NO_STAT error condition
- X *
- X * Revision 1.3 87/04/13 09:46:09 sahayman
- X * Make sure to do answerback() on unsuccessful messages (mesg n)
- X * as well as successful.
- X *
- X * Revision 1.2 87/04/06 02:16:30 sahayman
- X * Print a "However ... " message when unable to deliver to some
- X * ttys but able to deliver to others.
- X *
- X */
- X#include "msg.h"
- X#include <setjmp.h>
- X#include <signal.h>
- X#include <ctype.h>
- X
- Xstatic jmp_buf timeout;
- X
- X
- Xstatic
- Xwakeup()
- X{
- X longjmp( timeout, 1 );
- X}
- X
- X
- X
- Xint
- Xdeliver( sender, user, message, fromroot )
- Xchar *sender, *user, *message;
- X{
- X struct utmp ut;
- X FILE *fp, *term;
- X char terminal[40]; /* should be enough ... */
- X int found = 0, errcode = 0;
- X int however = 0; /* Should we print a "however ...." msg */
- X struct stat sbuf;
- X char line[sizeof(ut.ut_line)+5];
- X char successful_line[sizeof(ut.ut_line)+5];
- X int (*osig)();
- X#ifdef SAVEMSG
- X int uid = -1;
- X#endif
- X
- X successful_line[0] = '\0';
- X
- X if ( (fp=fopen( UTMP, "r" )) == FPNULL ) {
- X errmsg( NO_UTMP, hostname, syserr() );
- X return( NO_UTMP );
- X }
- X /* keep on until end of file in case s/he's signed on more than once */
- X while ( fread( &ut, sizeof(struct utmp), 1, fp ) == 1 ) {
- X if ( strncmp( user, ut.ut_name, sizeof(ut.ut_name) ) != 0 )
- X continue;
- X#ifdef SYSV_UTMP
- X if ( ut.ut_type != USER_PROCESS )
- X continue;
- X#endif
- X found++;
- X (void) strncpy( line, ut.ut_line, sizeof(ut.ut_line) );
- X line[sizeof(ut.ut_line)] = '\0';
- X (void) sprintf( terminal, "%s%s", DEV, line );
- X /* stat it to see if we're allowed to write */
- X if ( stat(terminal,&sbuf) == 0 ) {
- X#ifdef SAVEMSG
- X uid = sbuf.st_uid;
- X#endif
- X if ( ((sbuf.st_mode&ALLOW)==0) && !fromroot ) {
- X errmsg( MESG_OFF, user, hostname, line );
- X however++;
- X errcode++;
- X } else {
- X if ( setjmp( timeout ) ) {
- X errmsg( TIMEOUT, user, hostname, line );
- X however++;
- X } else {
- X osig = signal(SIGALRM, wakeup);
- X alarm( 5 );
- X if ( (term=fopen(terminal,"w")) != NULL ) {
- X fprintf(term, "\n\007%s: %s\n", sender, message);
- X /* we need this fflush() or else it would hang in the
- X fclose() after we've dealt with the alarm() */
- X fflush( term );
- X strcpy( successful_line, line );
- X }
- X }
- X alarm( 0 );
- X signal(SIGALRM, osig);
- X if (term == NULL) {
- X errmsg( NO_WRITE, user, hostname, line, syserr() );
- X however++;
- X errcode++;
- X } else
- X fclose( term );
- X }
- X#ifdef ANSWERBACK
- X answerback( ANSWER, user, line );
- X#endif
- X } else {
- X errmsg( NO_STAT, terminal, user, hostname, syserr() );
- X however++;
- X errcode++;
- X }
- X }
- X (void) fclose( fp );
- X#ifdef SAVEMSG
- X /* note that these saves it even if mesg n was set */
- X if ( found && uid != -1 )
- X savemsg( uid, user, sender, message );
- X#endif
- X if ( !found ) {
- X errmsg( NOT_ON, user, hostname );
- X errcode++;
- X }
- X /*
- X * A message like "so-and-so (ttyxx) is not receiving messages"
- X * is not too helpful when they are receiving messages
- X * on another terminal. So mention that.
- X * ..sah 87/04/06
- X */
- X
- X if ( however && successful_line[0] ) {
- X errmsg( HOWEVER, user, hostname, successful_line );
- X }
- X return( errcode );
- X}
- X
- X
- X#define DEL (127)
- X
- Xsanitize( mbuf, copy )
- Xchar *mbuf;
- Xchar *copy;
- X{
- X char *p, *r;
- X /*
- X * Remove control characters to prevent nasties.
- X * Previously allowed isspace(*p), but having a \r in a message
- X * is asking for forgeries. isprint() is sufficient.
- X * (And good programmers always use isascii() first, right?)
- X */
- X for ( p = mbuf, r = copy; *p; p++,r++ ) {
- X if ( ! isascii( *p ) ) {
- X *r++ = '\\';
- X *p = toascii( *p );
- X }
- X if ( ! isprint(*p) ) {
- X if ( *p == '\t' )
- X *r = ' ';
- X else if ( iscntrl( *p ) ) {
- X *r++ = '^';
- X if ( *p == DEL )
- X *r = '?';
- X else
- X *r = *p + '@';
- X } else /* this shouldn't happen, but what the hell */
- X *r = 'X';
- X } else
- X *r = *p;
- X }
- X}
- END_OF_FILE
- if test 4264 -ne `wc -c <'./Common/deliver.c'`; then
- echo shar: \"'./Common/deliver.c'\" unpacked with wrong size!
- fi
- # end of './Common/deliver.c'
- fi
- if test -f './Common/errtext.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Common/errtext.c'\"
- else
- echo shar: Extracting \"'./Common/errtext.c'\" \(2177 characters\)
- sed "s/^X//" >'./Common/errtext.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /usr/source/mfcf/msg/common/RCS/errtext.c,v 1.3 89/01/08 03:16:36 jmsellens Exp $";
- X#endif
- X
- X#if 0
- X/*
- X * $Log: errtext.c,v $
- X * Revision 1.3 89/01/08 03:16:36 jmsellens
- X * Changed BADHOST error message to not mention hosts file, since
- X * we don't use it any longer.
- X *
- X * Revision 1.2 88/09/25 02:40:49 jmsellens
- X * added message for BAD_VERSION
- X *
- X * Revision 1.1 87/08/06 19:06:32 sahayman
- X * Initial revision
- X *
- X */
- X#endif
- X
- X/* msgtext.c
- X Text of error messages produced by the system
- X*/
- X
- X#include "msg.h"
- X
- Xchar *errmessages[] = {
- X /* OK */
- X "",
- X /* NOT_ON - user, host */
- X "%s@%s is not signed on",
- X /* NO_WRITE - user, host, ut.u_line, syserr() */
- X "couldn't write to %s@%s (%s): %s",
- X /* BAD_HOST - host */
- X "host '%s' is unknown",
- X /* NO_UTMP - host, syserr() */
- X "couldn't open utmp on host '%s': %s",
- X /* BAD_ARGS - not used I think */
- X "bad argument(s)",
- X /* NO_CONNECT - host syserr() */
- X "couldn't connect to daemon on host '%s': %s (not running?)",
- X /* FATAL - not used I think */
- X "fatal error",
- X /* NO_ACK - host */
- X "didn't receive acknowledgement from host '%s'",
- X /* REMOTE_WRITE - host, syserr() */
- X "error writing to host '%s': %s",
- X /* REMOTE_READ - host, syserr() */
- X "error writing from host '%s': %s",
- X /* MESG_OFF user, host, ut.u_line */
- X "%s@%s (%s) is not receiving messages",
- X /* NO_REPLY user, ut.u_line */
- X "WARNING: Your terminal (%s on %s) cannot be written to",
- X /* TIMEOUT user, host, ut.u_line */
- X "timed out writing to %s@%s (%s) - terminal paging set?",
- X /* ANSWER user, host, line, answerbackmessage */
- X "%s@%s (%s): %s",
- X /* ANS_WARN user, line, answerbackmessage */
- X "%s on %s: Answerback message set to '%s'",
- X /* NO_TTY */
- X "WARNING: You are not on a terminal",
- X /* HOWEVER */
- X "However, %s@%s (%s) received the message",
- X /* NO_STAT - terminal, user, host, syserr() */
- X "Couldn't stat '%s' of %s@%s: %s - message not delivered",
- X /* BAD_VERSION - remote version, our version */
- X "Client version (%d) newer than server (%d) - can't understand you",
- X 0
- X};
- END_OF_FILE
- if test 2177 -ne `wc -c <'./Common/errtext.c'`; then
- echo shar: \"'./Common/errtext.c'\" unpacked with wrong size!
- fi
- # end of './Common/errtext.c'
- fi
- if test -f './Common/misc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Common/misc.c'\"
- else
- echo shar: Extracting \"'./Common/misc.c'\" \(457 characters\)
- sed "s/^X//" >'./Common/misc.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: misc.c,v 1.1 87/08/06 19:06:34 sahayman Exp $";
- X#endif
- X
- X#if 0
- X/*
- X * $Log: misc.c,v $
- X * Revision 1.1 87/08/06 19:06:34 sahayman
- X * Initial revision
- X *
- X */
- X#endif
- X
- X/* misc.c
- X miscellaneous routines
- X*/
- X
- X
- Xextern int sys_nerr, errno;
- Xextern char *sys_errlist[], *sprintf();
- X
- Xchar *
- Xsyserr()
- X{
- X static char buf[80];
- X
- X return( (errno<sys_nerr) ? sys_errlist[errno] :
- X sprintf(buf,"Unknown error %d", errno) );
- X}
- END_OF_FILE
- if test 457 -ne `wc -c <'./Common/misc.c'`; then
- echo shar: \"'./Common/misc.c'\" unpacked with wrong size!
- fi
- # end of './Common/misc.c'
- fi
- if test -f './Common/savemsg.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Common/savemsg.c'\"
- else
- echo shar: Extracting \"'./Common/savemsg.c'\" \(3173 characters\)
- sed "s/^X//" >'./Common/savemsg.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /source/users/msg/Common/RCS/savemsg.c,v 1.8 91/08/13 23:57:35 jmsellens Exp $";
- X#endif
- X
- X#if 0
- X/*
- X * $Log: savemsg.c,v $
- X * Revision 1.8 91/08/13 23:57:35 jmsellens
- X * s/eprintf/errprintf/ to avoid libuw clash
- X *
- X * Revision 1.7 91/08/13 23:57:05 jmsellens
- X * realuser stuff
- X *
- X * Revision 1.6 90/12/29 22:01:03 jmsellen
- X * Avoid PMBECOME, and handle DUMBSHORT machines
- X *
- X * Revision 1.5 88/09/25 03:03:29 jmsellens
- X * call syserr() is pmbecome() fails
- X *
- X * Revision 1.4 87/10/19 18:29:11 sahayman
- X * Use pmbecome() to become different users, since the simple
- X * seteuid( old_euid ) after you seteuid (someone) won't work.
- X *
- X * Revision 1.2 87/08/06 20:17:31 sahayman
- X * Write /usr/tmp/msg.user file by doing a seteuid(user) first, so that
- X * it has a chance of working when /usr/tmp is an NFS partition.
- X * No longer writes ~/.msg.
- X *
- X * Revision 1.1 87/08/06 19:06:40 sahayman
- X * Initial revision
- X *
- X */
- X#endif
- X
- X#include "msg.h"
- X#include <pwd.h>
- X#ifdef REALUSER
- X#include <mfcf/libuw/standard.h>
- X#endif
- X
- X
- Xsavemsg( uid, recipient, sender, msg )
- Xint uid;
- Xchar *recipient, *sender, *msg;
- X{
- X char fname[100]; /* lots o' room */
- X FILE *fp;
- X struct passwd *pwd;
- X#ifdef PMBECOME
- X int old_euid = geteuid();
- X#endif /* PMBECOME */
- X
- X /*
- X * Original code used to write into ~/.msg. No more.
- X */
- X
- X /* truncate the recipient for lookup */
- X if ( strlen(recipient) > sizeof(((struct utmp *)NULL)->ut_name) )
- X recipient[sizeof(((struct utmp *)NULL)->ut_name)] = '\0';
- X if ((pwd = getpwnam(recipient)) == (struct passwd *) NULL) {
- X#ifdef DUMBSHORT
- X /* loop through the whole passwd file looking for a
- X truncated match */
- X struct utmp *ut; /* just for sizeof() */
- X setpwent();
- X while ( (pwd = getpwent()) != (struct passwd *) NULL ) {
- X if ( strncmp(recipient,pwd->pw_name,sizeof(ut->ut_name)) == 0 )
- X break;
- X }
- X if ( pwd == (struct passwd *) NULL )
- X return;
- X recipient = pwd->pw_name;
- X#else
- X return;
- X#endif
- X }
- X#ifdef REALUSER
- X recipient = realuser( pwd );
- X#endif
- X
- X
- X /* now, put it where it really belongs, in MSGFILE */
- X
- X#ifdef PMBECOME
- X /*
- X * This seteuid() business is so that this can work
- X * when /usr/tmp is an NFS thingy, and root on a client
- X * can only creat things there owned by -2, so the old
- X * scheme of opening the file and then chowning it wouldn't work.
- X */
- X
- X#ifdef old
- X if ( seteuid( pwd->pw_uid ) == -1 ) {
- X errprintf("savemsg: Cannot seteuid(%d)", pwd->pw_uid);
- X#else
- X if ( pmbecome( pwd->pw_uid ) == -1 ) {
- X errprintf("savemsg: Cannot pmbecome(%d): %s", pwd->pw_uid, syserr());
- X#endif
- X
- X /*
- X * Keep going, it might work...
- X */
- X }
- X#endif /* PMBECOME */
- X
- X strcpy( fname, MSGFILE );
- X strcat( fname, recipient );
- X
- X (void) unlink( fname ); /* in case it already exists */
- X
- X if ( (fp = fopen( fname, "w" ) ) != NULL ) {
- X (void) fchmod( fileno(fp), 0600 );
- X (void) fchown( fileno(fp), pwd->pw_uid, -1 );
- X fprintf( fp, "%s: %s\n", sender, msg );
- X (void) fclose( fp );
- X }
- X
- X#ifdef PMBECOME
- X if ( pmbecome(0) == -1 )
- X errprintf("savemsg: Cannot pmbecome(0): %s", syserr());
- X#endif /* PMBECOME */
- X}
- END_OF_FILE
- if test 3173 -ne `wc -c <'./Common/savemsg.c'`; then
- echo shar: \"'./Common/savemsg.c'\" unpacked with wrong size!
- fi
- # end of './Common/savemsg.c'
- fi
- if test ! -d './Include' ; then
- echo shar: Creating directory \"'./Include'\"
- mkdir './Include'
- fi
- if test -f './Include/msg.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Include/msg.h'\"
- else
- echo shar: Extracting \"'./Include/msg.h'\" \(2892 characters\)
- sed "s/^X//" >'./Include/msg.h' <<'END_OF_FILE'
- X/* msg.h
- X header file for msg and msgd
- X*/
- X
- X/*
- X * $Header: /usr/source/users/msg/Include/RCS/msg.h,v 1.9 91/03/08 20:13:16 jmsellens Exp Locker: jmsellens $
- X *
- X */
- X
- X/* Options */
- X#include "msgoptions.h"
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <utmp.h>
- X#define UTMP "/etc/utmp" /* why isn't this in utmp.h?? */
- X#ifdef USER_PROCESS
- X#define SYSV_UTMP
- X#endif
- X#include <sys/stat.h>
- X#define ALLOW ((S_IWRITE>>3)|(S_IWRITE>>6))
- X#ifdef VARARGS
- X#include <varargs.h>
- X#endif
- X
- X#define DEV "/dev/"
- X#define MSGFILE "/usr/tmp/msg." /* where to save messages, append userid */
- X#define PMSGFILE "/usr/tmp/pmsg." /* where to save outgoing messages */
- X#define ANSBACK "/usr/tmp/mesg." /* where asnwerback message might be */
- X
- X#define private static
- X
- Xextern char hostname[];
- Xextern char *syserr();
- X
- X/*
- X * Following are in network byte order.
- X */
- Xtypedef struct header {
- X int slen; /* sender length */
- X int ulen; /* userid length */
- X int mlen; /* message length */
- X} header;
- X
- X/* This version header was added after the original version of msg had
- X been installed and was running. To provide compatibility with versions
- X of msg that do not send a version as the first information, this
- X version struct must be twelve bytes long, and the first int is always
- X a 0, because if it is non-zero you can assume that it is a sender
- X length in a header, and not a version struct.
- X*/
- Xtypedef union version {
- X header h;
- X struct v {
- X int zero;
- X int vnum; /* version number */
- X int filler;
- X } v;
- X} version;
- X#define VERSION (1) /* current version */
- X
- X
- Xextern char *errmessages[];
- X/* error codes for message - msgtext.c relies on this ordering */
- X#define OK (0)
- X#define VERSION_OK OK /* got a version, and we accept it */
- X#define NOT_ON (1) /* user not signed on */
- X#define NO_WRITE (2) /* couldn't write to terminal */
- X#define BAD_HOST (3) /* host doesn't exist */
- X#define NO_UTMP (4) /* couldn't open /etc/utmp */
- X#define BAD_ARGS (5) /* bad arguments */
- X#define NO_CONNECT (6) /* couldn't connect to remote host */
- X#define FATAL (7) /* fatal error */
- X#define NO_ACK (8) /* no result from remote host */
- X#define REMOTE_WRITE (9) /* write error to remote host */
- X#define REMOTE_READ (10) /* read error from remote host */
- X#define MESG_OFF (11) /* dest user has mesg n set */
- X#define NO_REPLY (12) /* can't get replies */
- X#define TIMEOUT (13) /* timeout while writing to user's terminal */
- X#define ANSWER (14) /* asnwerback message */
- X#define ANS_WARN (15) /* user has answerback msg set */
- X#define NO_TTY (16) /* user is not on a tty */
- X#define HOWEVER (17) /* However, another tty was writable. */
- X#define NO_STAT (18) /* couldn't stat tty */
- X#define BAD_VERSION (19) /* client newer than server */
- X
- X#define ERROR_MESSAGE (99) /* error message being returned from msgd */
- X
- X#define FPNULL ((FILE *)NULL)
- X#define CPNULL ((char *)NULL)
- X#define TRUE (1)
- X#define FALSE (0)
- END_OF_FILE
- if test 2892 -ne `wc -c <'./Include/msg.h'`; then
- echo shar: \"'./Include/msg.h'\" unpacked with wrong size!
- fi
- # end of './Include/msg.h'
- fi
- if test -f './Include/msgoptions.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Include/msgoptions.h'\"
- else
- echo shar: Extracting \"'./Include/msgoptions.h'\" \(1588 characters\)
- sed "s/^X//" >'./Include/msgoptions.h' <<'END_OF_FILE'
- X/* msgoptions.h
- X separate options file, so I can #inlcude it in an Imakefile
- X*/
- X
- X/*
- X * $Header: /usr/source/users/msg/Include/RCS/msg.h,v 1.9 91/03/08 20:13:16 jmsellens Exp Locker: jmsellens $
- X *
- X */
- X
- X/* Options */
- X/* define PMBECOME if you want to use the Waterloo pmbecome() routine
- X which allows you to seteuid() to a user, and seteuid() back to root
- X later. Only needed if the MSGFILE is on a partition that root can't
- X write, such as on pre 4.0 SunOS diskless clients. */
- X/* #define PMBECOME */
- X
- X/* define SAVEMSG to save received messages in MSGFILE */
- X#define SAVEMSG
- X
- X/* define ANSWERBACK to allow the use of answerback files set up by
- X mesg to send back to the sender when a message is received. */
- X#define ANSWERBACK
- X
- X/* define REMOTE to always use the daemon to deliver instead of doing
- X local delivery when possible. This means msg doesn't have to be
- X setuid/setgid, but it's also slower. */
- X/* #define REMOTE */
- X
- X/* define VARARGS if you have the varargs stuff, including vprintf and
- X friends. */
- X#define VARARGS
- X
- X/* define DUMBSHORT if you're silly enough to have long userids in the
- X passwd file, but short userids everywhere else. We were silly enough
- X to be doing this on our MIPS machines ... */
- X/* #define DUMBSHORT */
- X
- X/* define REALUSER if you want to use the MFCF realuser() routine to find
- X out your "real" campus-wide userid and use that as the return address.
- X This won't be useful outside Waterloo, and I hope I remembered to remove
- X the "-luw" from the Makefile before sending it into the outside world. */
- X/* #define REALUSER */
- END_OF_FILE
- if test 1588 -ne `wc -c <'./Include/msgoptions.h'`; then
- echo shar: \"'./Include/msgoptions.h'\" unpacked with wrong size!
- fi
- # end of './Include/msgoptions.h'
- fi
- if test -f './Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Makefile'\"
- else
- echo shar: Extracting \"'./Makefile'\" \(385 characters\)
- sed "s/^X//" >'./Makefile' <<'END_OF_FILE'
- X# Makes msg and msgd and mesg, one hopes.
- X
- XTOP = /software/users
- XBINDIR = $(TOP)/bin
- XSERVDIR = $(TOP)/servers
- XMANDIR = $(TOP)/man
- X
- XMACROS = BINDIR=$(BINDIR) SERVDIR=$(SERVDIR) MANDIR=$(MANDIR)
- X
- Xall\
- Xclean\
- Xinstall:
- X cd msg && $(MAKE) $(MFLAGS) $(MACROS) $@
- X cd msgd && $(MAKE) $(MFLAGS) $(MACROS) $@
- X cd mesg && $(MAKE) $(MFLAGS) $(MACROS) $@
- X cd Man && $(MAKE) $(MFLAGS) $(MACROS) $@
- END_OF_FILE
- if test 385 -ne `wc -c <'./Makefile'`; then
- echo shar: \"'./Makefile'\" unpacked with wrong size!
- fi
- # end of './Makefile'
- fi
- if test ! -d './Man' ; then
- echo shar: Creating directory \"'./Man'\"
- mkdir './Man'
- fi
- if test -f './Man/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Man/Makefile'\"
- else
- echo shar: Extracting \"'./Man/Makefile'\" \(448 characters\)
- sed "s/^X//" >'./Man/Makefile' <<'END_OF_FILE'
- XMANDIR = /software/users/man
- XMANUSER = bin
- XMANMODE = 444
- X
- Xall:
- X echo All made in Man
- Xclean:
- X echo All clean in Man
- Xinstall:
- X cp -p msg.1 $(MANDIR)/man1
- X chown $(MANUSER) $(MANDIR)/man1/msg.1
- X chmod $(MANMODE) $(MANDIR)/man1/msg.1
- X cp -p msgd.8 $(MANDIR)/man8
- X chown $(MANUSER) $(MANDIR)/man8/msgd.8
- X chmod $(MANMODE) $(MANDIR)/man8/msgd.8
- X cp -p mesg.8 $(MANDIR)/man8
- X chown $(MANUSER) $(MANDIR)/man8/mesg.8
- X chmod $(MANMODE) $(MANDIR)/man8/mesg.8
- END_OF_FILE
- if test 448 -ne `wc -c <'./Man/Makefile'`; then
- echo shar: \"'./Man/Makefile'\" unpacked with wrong size!
- fi
- # end of './Man/Makefile'
- fi
- if test -f './Man/mesg.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Man/mesg.1'\"
- else
- echo shar: Extracting \"'./Man/mesg.1'\" \(1937 characters\)
- sed "s/^X//" >'./Man/mesg.1' <<'END_OF_FILE'
- X.\" Copyright (c) 1987 Regents of the University of California.
- X.\" All rights reserved.
- X.\"
- X.\" Redistribution and use in source and binary forms are permitted
- X.\" provided that the above copyright notice and this paragraph are
- X.\" duplicated in all such forms and that any documentation,
- X.\" advertising materials, and other materials related to such
- X.\" distribution and use acknowledge that the software was developed
- X.\" by the University of California, Berkeley. The name of the
- X.\" University may not be used to endorse or promote products derived
- X.\" from this software without specific prior written permission.
- X.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X.\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X.\"
- X.\" @(#)mesg.1 6.3 (Berkeley) 7/9/88
- X.\"
- X.TH MESG 1 "18 July 1983"
- X.SH NAME
- Xmesg \- permit or deny messages
- X.SH SYNOPSIS
- X.B mesg
- X[
- X.B n
- X] [
- X.B y
- X]
- X[answerback message]
- X.SH DESCRIPTION
- X.I Mesg
- Xwith argument
- X.B n
- Xforbids messages via
- X.I write
- Xand
- X.IR talk (1)
- Xby revoking non-user
- Xwrite permission on the user's terminal.
- X.I Mesg
- Xwith argument
- X.B y
- Xreinstates permission.
- XAll by itself,
- X.I mesg
- Xreports the current state and answerback message without changing it.
- X.PP
- XThe answerback message
- Xis used as an automatic response to anyone who tries to send you a msg.
- XThe existing answerback message is removed on subsequent
- X.I mesg
- Xcommand invocations (except when no arguments are given).
- X.SH EXAMPLE
- Xmesg n Please send me mail instead.
- X.SH BUGS
- X.I mesg
- Xwill not work within a
- X.IR script (1)
- Xsession because there is no way for it to find out what terminal
- Xyou are really signed on to.
- X.SH FILES
- X/dev/tty*
- X.br
- X/usr/tmp/mesg.tty*
- X.SH "SEE ALSO"
- Xwrite(1), talk(1)
- X.SH DIAGNOSTICS
- XExit status is 0 if messages are receivable,
- X1 if not, 2 on error.
- X.SH NOTE
- XAnswerback messages are a Waterloo addition.
- END_OF_FILE
- if test 1937 -ne `wc -c <'./Man/mesg.1'`; then
- echo shar: \"'./Man/mesg.1'\" unpacked with wrong size!
- fi
- # end of './Man/mesg.1'
- fi
- if test -f './Man/msg.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Man/msg.1'\"
- else
- echo shar: Extracting \"'./Man/msg.1'\" \(3411 characters\)
- sed "s/^X//" >'./Man/msg.1' <<'END_OF_FILE'
- X.TH MSG 1 "University of Waterloo"
- X.SH NAME
- Xmsg \- write a short message to other users
- X.SH SYNOPSIS
- X.B msg
- X[
- X.B \-l
- X]
- X[
- X.B \-m
- X.I message
- X]
- X[
- X.B \-p
- X]
- X[
- X.B \-r
- X]
- X[
- X.B \-t
- X]
- Xuser ...
- X.SH DESCRIPTION
- X.I Msg
- Xwrites a one-line message to a given set of users.
- XIf a user is logged in more than once, each instance of that user will receive
- Xthe message.
- X.PP
- XPrevious versions of
- X.I msg
- Xallowed the last argument to be the message. This confusing behaviour
- Xis no longer available.
- X.PP
- XThe message is preceded by a beep,
- Xthe login name of the sender,
- Xand the name of the sender's machine.
- XIf the sender is set-userid to someone other than the super-user,
- Xthen the real (set-userid) name is printed in parentheses.
- XReplies should use the login name, not the parenthesized (set-userid) name,
- Xsince the login name is the way
- X.I msg
- Xfinds people.
- X.PP
- X.I Msg
- Xworks across machines, as long as the remote machine is running the
- X.IR msgd (8)
- Xmessage daemon.
- XTo do this,
- X.I user
- Xshould be of the form
- X.I person@machine
- X(or the old-style
- X.I machine!person
- X).
- X.PP
- XIt is very annoying to receive a message just before your screen clears,
- Xmaking it impossible to read the message.
- XTo help alleviate this problem,
- X.I msg
- Xwill save a copy of the message and you can use the
- X.I -l
- Xoption to repeat the last message you received.
- X.PP
- XIt is also annoying to discover a message on your screen but not know
- Xwhen it was sent. Use \fB\-t\fP to find out.
- X.SH OPTIONS
- X.TP 10
- X.B \-r
- XIf the
- X.BR \-r ,
- Xoption is given,
- X.I msg
- Xwill look in the file
- X.I /usr/tmp/msg.userid
- Xfile to find out the last person who sent you a message,
- Xand assume you want to reply to them.
- X(Additional recipients can still be specified, so the same
- Xrules apply about which arguments are messages and which are users.
- XThe easiest thing to use is
- X.I "msg -r"
- Xwith no other arguments; type the reply on the next line.)
- X.TP
- X.B \-l
- XList the last message received.
- XThis simply shows the file
- X.I /usr/tmp/msg.userid
- Xso that you don't have to remember the name.
- X.I "msg -lr"
- Xis a handy way to show the last message and prompt for a reply.
- X.TP
- X.B \-t
- XShow the time that the last message was received. Handy combinations are
- X.B \-tl
- Xand
- X.B \-tlr.
- X.TP
- X.B \-p
- XUse the text of the previous message you sent (saved in the file
- X.IR /usr/tmp/pmsg.userid )
- Xas the text of this message. This is handy if you mistyped someone's
- Xuserid, and typed a long message only to have it fail.
- X.PP
- X.I Msg
- Xobeys the restrictions of
- X.IR mesg (1).
- X.SH "SEE ALSO"
- Xwrite(1), mail(1), talk(1), msgd(8)
- X.SH EXAMPLES
- X.TP 10
- X% msg -m 'This is the message in quotes.' user1 user2
- XQuoting a string makes it one argument as far as Unix is concerned.
- X.TP 10
- X% msg user1 user2
- X<type the message here, on the next line>
- X.TP 10
- X% msg -r
- X<Type a reply here to the last person who sent you a msg.>
- X.TP 10
- X% msg -r -m 'Or you can put the reply here.'
- X.SH FILES
- X.TP
- X/usr/tmp/msg.userid
- XContains the last message received.
- X.TP
- X/usr/tmp/pmsg.userid
- XContains the text of the previous message sent or attempted.
- X.TP
- X/usr/tmp/mesg.userid
- XAnswerback message - set by mesg(1).
- X.SH AUTHOR
- XThe staff of the Math Faculty Computing Facility at the University
- Xof Waterloo, Waterloo, Ontario Canada. Bug reports can be sent
- Xto either or both of John Sellens (jmsellens@watmath.waterloo.edu)
- Xor uw.mfcf.bugs@watmath.waterloo.edu.
- X.SH COPYRIGHT
- XCopyright 1988, 1989, 1990 University of Waterloo
- X.br
- XRedistribution is permitted.
- END_OF_FILE
- if test 3411 -ne `wc -c <'./Man/msg.1'`; then
- echo shar: \"'./Man/msg.1'\" unpacked with wrong size!
- fi
- # end of './Man/msg.1'
- fi
- if test -f './Man/msgd.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./Man/msgd.8'\"
- else
- echo shar: Extracting \"'./Man/msgd.8'\" \(728 characters\)
- sed "s/^X//" >'./Man/msgd.8' <<'END_OF_FILE'
- X.TH MSGD 8 "University of Waterloo"
- X.SH NAME
- Xmsgd \- remote message daemon
- X.SH DESCRIPTION
- X.I Msgd
- Xaccepts connections from remote
- X.IR msg (1)
- Xcommands for delivery to users on the local system.
- X.PP
- X.I Msgd
- Xis normally run under
- X.IR inetd (8).
- X.SH FILES
- X.IP /etc/services
- Xdefines which port
- X.I msgd
- Xwill use
- X.IP /etc/inetd.conf
- Xconfig file for
- X.I inetd
- X.SH "SEE ALSO"
- Xmsg(1), mesg(1)
- X.SH AUTHOR
- XThe staff of the Math Faculty Computing Facility at the University
- Xof Waterloo, Waterloo, Ontario Canada. Bug reports can be sent
- Xto either or both of John Sellens (jmsellens@watmath.waterloo.edu)
- Xor uw.mfcf.bugs@watmath.waterloo.edu.
- X.SH COPYRIGHT
- XCopyright 1988, 1989, 1990 University of Waterloo
- X.br
- XRedistribution is permitted.
- END_OF_FILE
- if test 728 -ne `wc -c <'./Man/msgd.8'`; then
- echo shar: \"'./Man/msgd.8'\" unpacked with wrong size!
- fi
- # end of './Man/msgd.8'
- fi
- if test -f './inetd.conf' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./inetd.conf'\"
- else
- echo shar: Extracting \"'./inetd.conf'\" \(61 characters\)
- sed "s/^X//" >'./inetd.conf' <<'END_OF_FILE'
- Xmsg stream tcp nowait root /software/users/servers/msgd msgd
- END_OF_FILE
- if test 61 -ne `wc -c <'./inetd.conf'`; then
- echo shar: \"'./inetd.conf'\" unpacked with wrong size!
- fi
- # end of './inetd.conf'
- fi
- if test ! -d './mesg' ; then
- echo shar: Creating directory \"'./mesg'\"
- mkdir './mesg'
- fi
- if test -f './mesg/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./mesg/Makefile'\"
- else
- echo shar: Extracting \"'./mesg/Makefile'\" \(378 characters\)
- sed "s/^X//" >'./mesg/Makefile' <<'END_OF_FILE'
- X# Needs to be setuid root so we can remove others' answerback files
- X
- XBINDIR = /software/users/bin
- XMANDIR = /software/users/man
- X
- XNAME = mesg
- XOWNER=root
- XGROUP=staff
- XMODE=4755
- X
- XOBJECT = mesg.o
- X
- Xall: $(NAME)
- X
- X$(NAME): $(OBJECT)
- X cc -o $(NAME) $(OBJECT)
- X
- Xinstall: $(NAME)
- X install -s -o $(OWNER) -g $(GROUP) -m $(MODE) $(NAME) $(BINDIR)/$(NAME)
- X
- Xclean:
- X rm -f a.out core *.o $(NAME)
- END_OF_FILE
- if test 378 -ne `wc -c <'./mesg/Makefile'`; then
- echo shar: \"'./mesg/Makefile'\" unpacked with wrong size!
- fi
- # end of './mesg/Makefile'
- fi
- if test -f './mesg/mesg.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./mesg/mesg.c'\"
- else
- echo shar: Extracting \"'./mesg/mesg.c'\" \(4528 characters\)
- sed "s/^X//" >'./mesg/mesg.c' <<'END_OF_FILE'
- X/*
- X * Copyright (c) 1987 Regents of the University of California.
- X * All rights reserved.
- X *
- X * Redistribution and use in source and binary forms are permitted
- X * provided that the above copyright notice and this paragraph are
- X * duplicated in all such forms and that any documentation,
- X * advertising materials, and other materials related to such
- X * distribution and use acknowledge that the software was developed
- X * by the University of California, Berkeley. The name of the
- X * University may not be used to endorse or promote products derived
- X * from this software without specific prior written permission.
- X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X */
- X
- X#ifndef lint
- Xchar copyright[] =
- X"@(#) Copyright (c) 1987 Regents of the University of California.\n\
- X All rights reserved.\n";
- X#endif /* not lint */
- X
- Xstatic char *sccsid = "@(#)mesg.c 4.2 (Berkeley) 10/18/80";
- X/*
- X * mesg -- set current tty to accept or
- X * forbid write permission.
- X *
- X * mesg [yn] "answerback message"
- X * y allow messages
- X * n forbid messages
- X * answerback is what the other guy gets told (Waterloo)
- X * needs to be setuid root to get rid of other people's
- X * old answerback message files
- X *
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <utmp.h>
- X#include <pwd.h>
- X
- X#define ANSWERBACK_FMT "/usr/tmp/mesg.%s"
- X
- Xmain(argc, argv)
- X char **argv;
- X{
- X int uid, mode, r=0;
- X char *tty, *p, *rindex(), *ttyname();
- X FILE *fp;
- X int i_own_answerback = 0;
- X struct stat sbuf;
- X struct passwd *pw;
- X char answerback[200];
- X
- X (void) umask(022); /* so we can read answerback file */
- X tty = ttyname(2);
- X if (tty == 0)
- X error("Cannot determine name of current terminal", (char *)0);
- X if ( (p=rindex(tty,'/')) != NULL )
- X p++;
- X else
- X p = tty;
- X /*
- X * If this isn't a login session, use of mesg is meaningless.
- X */
- X uid = getuid();
- X pw = getpwuid(uid);
- X if (pw == NULL) {
- X fprintf(stderr, "mesg: Can't find your uid (%d) in the password file\n", uid);
- X exit(2);
- X }
- X if (!in_utmp(pw->pw_name, p)) {
- X fprintf(stderr, "mesg: Current terminal session on %s is not a login session\n", tty);
- X exit(2);
- X }
- X /* find name of answerback file */
- X (void) sprintf( answerback, ANSWERBACK_FMT, p );
- X /* Now make sure that if the answerback file exists, it belongs to
- X the current user */
- X if ( lstat( answerback, &sbuf ) == 0 ) {
- X if (sbuf.st_uid == uid)
- X i_own_answerback = 1;
- X else
- X (void) unlink(answerback);
- X }
- X if(stat(tty, &sbuf) < 0) error("cannot stat", tty);
- X /*
- X * must be root before here so we can get rid of other persons
- X * answerback file since sticky bit is on tmp directory.
- X * must be real user after here so he cant read/write *any* file
- X * by creating a link in the tmp directory.
- X */
- X setuid(uid);
- X if(argc < 2) {
- X if(sbuf.st_mode & 020)
- X printf( "is y\n" );
- X else { r=1;
- X printf( "is n\n" );
- X }
- X if (i_own_answerback) {
- X if ( (fp=fopen(answerback,"r")) != NULL ) {
- X int c;
- X while ( (c=getc(fp)) != EOF )
- X putc( c, stdout );
- X (void) fclose( fp );
- X } else
- X error("Can't read answerback file", answerback);
- X }
- X } else {
- X if (i_own_answerback)
- X (void) unlink(answerback);
- X if ( argv[1][0] == 'y' ) {
- X mode = sbuf.st_mode | 020;
- X } else if ( argv[1][0] == 'n' ) {
- X mode = sbuf.st_mode & ~022;
- X r = 1;
- X } else
- X error("usage: mesg [yn] [answerback message]", (char *)0);
- X if (chmod(tty, mode) < 0)
- X error("cannot change modes", tty);
- X if ( argc > 2 ) { /* write answerback message */
- X int i;
- X if ( (fp=fopen(answerback,"w")) == (FILE *)NULL )
- X error("Couldn't write answerback file", answerback);
- X for ( i=2; i<argc; i++ ) {
- X if ( i>2 )
- X putc( ' ', fp );
- X fputs( argv[i], fp );
- X }
- X putc( '\n', fp );
- X (void) fclose( fp );
- X }
- X }
- X exit(r);
- X}
- X
- Xerror(s, arg)
- Xchar *s, *arg;
- X{
- X fprintf(stderr,"mesg: %s", s);
- X if (arg)
- X perror(arg);
- X else
- X putc('\n', stderr);
- X exit(2);
- X}
- X
- X/*
- X * Does the given (user,tty) pair appear in the utmp file?
- X */
- Xin_utmp(user, tty)
- X char *user, *tty;
- X{
- X FILE *fp;
- X struct utmp utmp;
- X
- X if ((fp = fopen("/etc/utmp", "r")) == NULL)
- X return 0;
- X while (fread((char *)&utmp, sizeof utmp, 1, fp) == 1) {
- X if (strncmp(user, utmp.ut_name, sizeof utmp.ut_name) == 0 &&
- X strncmp(tty, utmp.ut_line, sizeof utmp.ut_line) == 0) {
- X#ifdef USER_PROCESS
- X if ( utmp.ut_type != USER_PROCESS )
- X continue;
- X#endif
- X fclose(fp);
- X return 1;
- X }
- X }
- X fclose(fp);
- X return 0;
- X}
- END_OF_FILE
- if test 4528 -ne `wc -c <'./mesg/mesg.c'`; then
- echo shar: \"'./mesg/mesg.c'\" unpacked with wrong size!
- fi
- # end of './mesg/mesg.c'
- fi
- if test ! -d './msg' ; then
- echo shar: Creating directory \"'./msg'\"
- mkdir './msg'
- fi
- if test -f './msg/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./msg/Makefile'\"
- else
- echo shar: Extracting \"'./msg/Makefile'\" \(927 characters\)
- sed "s/^X//" >'./msg/Makefile' <<'END_OF_FILE'
- X# Needs to be setuid root so that msg save files can be made and chown'd.
- X# Needs to be setgid tty so that we can write to ttys in /dev
- X
- XBINDIR = /software/users/bin
- XMANDIR = /software/users/man
- X
- XNAME = msg
- XOWNER=root
- XGROUP=tty
- XMODE=6555
- XCFLAGS= -I../Include $(DBX)
- X
- XOBJECT = msg.o remote.o deliver.o misc.o errtext.o savemsg.o answerback.o
- X
- Xall: $(NAME)
- X
- X$(NAME): $(OBJECT)
- X cc -o $(NAME) $(OBJECT)
- X
- Xinstall: $(NAME)
- X install -s -o $(OWNER) -g $(GROUP) -m $(MODE) $(NAME) $(BINDIR)/$(NAME)
- X
- Xclean:
- X rm -f a.out core *.o $(NAME)
- X
- X$(OBJECT): ../Include/msg.h ../Include/msgoptions.h
- X
- Xanswerback.o: ../Common/answerback.c
- X cc $(CFLAGS) -c ../Common/answerback.c
- X
- Xdeliver.o: ../Common/deliver.c
- X cc $(CFLAGS) -c ../Common/deliver.c
- X
- Xerrtext.o: ../Common/errtext.c
- X cc $(CFLAGS) -c ../Common/errtext.c
- X
- Xmisc.o: ../Common/misc.c
- X cc $(CFLAGS) -c ../Common/misc.c
- X
- Xsavemsg.o: ../Common/savemsg.c
- X cc $(CFLAGS) -c ../Common/savemsg.c
- END_OF_FILE
- if test 927 -ne `wc -c <'./msg/Makefile'`; then
- echo shar: \"'./msg/Makefile'\" unpacked with wrong size!
- fi
- # end of './msg/Makefile'
- fi
- if test -f './msg/msg.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./msg/msg.c'\"
- else
- echo shar: Extracting \"'./msg/msg.c'\" \(12537 characters\)
- sed "s/^X//" >'./msg/msg.c' <<'END_OF_FILE'
- X/*
- X * $Header: /source/users/msg/msg/RCS/msg.c,v 1.24 91/08/18 18:37:29 dgharriss Exp $
- X */
- X
- X/*
- X * msg.c
- X * MSG re-written to use a daemon
- X * John Sellens, University of Waterloo
- X */
- X
- X#include "msg.h"
- X#include <pwd.h>
- X#include <strings.h>
- X
- X#ifdef REALUSER
- X#include <mfcf/libuw/standard.h>
- X#endif
- X
- X/* global */ char hostname[80];
- Xprivate char *progname;
- X#define USERIDSPACE (80) /* lots of room */
- Xprivate char sender[USERIDSPACE];
- Xprivate char loginname[USERIDSPACE];
- Xprivate int uid; /* effective */
- Xprivate int ruid; /* real */
- X
- Xprivate char msg_file[80];
- Xprivate char pmsg_file[80];
- X
- Xextern char *syserr();
- Xextern char *ttyname();
- X
- Xprivate int getsender(), sendmsg();
- Xprivate void replywarn();
- Xprivate void usage();
- Xprivate void getprevious();
- Xprivate void putprevious();
- Xextern void fatal();
- X
- X#define SU (0) /* uid of super-user */
- X
- Xmain( argc, argv )
- Xint argc;
- Xchar *argv[];
- X{
- X register int i;
- X register int exitcode = 0;
- X int fromroot;
- X int useprevious = 0; /* send previous text as msg */
- X int cmdlinemsg = 0; /* msg is on cmd line */
- X char *p;
- X char message[1024]; /* to hold message */
- X char rawmsg[1024]; /* to hold unclean message */
- X char *tname; /* name of current tty */
- X char *reply = NULL, *reply_to();
- X
- X
- X int c;
- X extern int optind;
- X extern char *optarg;
- X
- X
- X progname = argv[0];
- X if ( argc == 1 )
- X usage();
- X
- X if ( gethostname( hostname, (int)sizeof(hostname) ) )
- X fatal( "Couldn't gethostname(): %s", syserr() );
- X
- X fromroot = getsender();
- X strcpy( msg_file, MSGFILE );
- X strcat( msg_file, loginname );
- X strcpy( pmsg_file, PMSGFILE );
- X strcat( pmsg_file, loginname );
- X
- X while (( c = getopt(argc, argv, "lm:prt")) != EOF ) {
- X switch( c ) {
- X case 'l':
- X list_msg();
- X break;
- X case 'm':
- X strcpy( rawmsg, optarg ); /* hope they don't have a giant msg */
- X cmdlinemsg++;
- X break;
- X case 'p':
- X useprevious++;
- X break;
- X case 'r':
- X if ( (reply = reply_to()) == NULL ) {
- X fatal( "Nobody to reply to in last message file '%s'",
- X msg_file );
- X }
- X break;
- X case 't':
- X list_msgtime();
- X break;
- X default:
- X usage();
- X }
- X }
- X if ( useprevious && cmdlinemsg )
- X fatal( "-m and -p can't be used together" );
- X
- X /* Tell 'em now so that the lastmsg comes before you get the replying
- X message, and tell them so they know who they're sending to, in
- X case it's wrong. */
- X if ( reply != NULL )
- X errprintf("Replying to '%s'", reply);
- X
- X /*
- X * Simpler to pretend the options weren't there. Skip over 'em.
- X * argv/argc is now a vector of user names.
- X */
- X argc -= optind;
- X argv += optind;
- X
- X
- X if ( (cmdlinemsg||useprevious) && reply == NULL && argc == 0 )
- X fatal( "No one to send message to" );
- X
- X /*
- X * Quietly exit if no recipients and no reply. This covers the case
- X * where all we got was the -l option.
- X */
- X if ( reply == NULL && argc == 0 )
- X exit(0);
- X
- X /* Old behaviour used - as last argument to indicate msg on stdin */
- X if ( strcmp("-", argv[argc-1]) == 0 ) {
- X errprintf( "'-' as last argument is obsolete - ignored" );
- X argc--;
- X }
- X
- X if ( useprevious ) {
- X getprevious( rawmsg, (int)sizeof(rawmsg) );
- X } else if ( ! cmdlinemsg ) {
- X if ( fgets( rawmsg, (int)sizeof(rawmsg), stdin ) == NULL ) {
- X /* assume user changed their mind */
- X return(0);
- X }
- X p = index(rawmsg, '\n');
- X if (p == NULL)
- X errprintf("Message truncated to %d characters.", sizeof(rawmsg) );
- X else
- X *p = NULL;
- X }
- X
- X if ( *rawmsg == '\0' ) /* No message to send. */
- X return(0);
- X sanitize( rawmsg, message );
- X
- X if ( useprevious )
- X printf( "Sending: %s\n", message );
- X else
- X putprevious( message );
- X
- X if( (tname=ttyname(0)) || (tname=ttyname(1)) || (tname=ttyname(2)) )
- X replywarn(tname); /* warn if can't get replies on this tty */
- X#if 0
- X /* Is this a good idea? -IAN! */
- X else
- X errmsg( NO_TTY );
- X#endif
- X
- X /*
- X * Send a reply if -r was used, also send to all other
- X * recipients on the command line.
- X */
- X
- X if ( reply != NULL && sendmsg(reply, message, fromroot) != OK )
- X exitcode++;
- X
- X while ( --argc >= 0 ) {
- X /* sendmsg() will destroy the argv[i] */
- X if ( sendmsg( *argv++, message, fromroot ) != OK )
- X exitcode++;
- X }
- X return( exitcode!=0 );
- X}
- X
- X
- X/*
- X * Find out who the sender is. Try getlogin(), and if that
- X * differs from the REAL uid, make sure both names appear.
- X * Return 1 if we are root, 0 otherwise.
- X */
- Xstatic int
- Xgetsender()
- X{
- X extern char *getlogin(), *getenv();
- X struct passwd *pw;
- X char pwname[USERIDSPACE];
- X char *glog;
- X
- X ruid = uid = getuid();
- X
- X /* Check out who we're running as */
- X if ( (pw=getpwuid(uid)) == NULL )
- X fatal("Your uid number (%d) isn't recognized.\n", uid);
- X if(pw->pw_name == NULL || pw->pw_name[0] == '\0')
- X fatal("No pwname is associated with uid %d.\n", uid);
- X#ifdef REALUSER
- X (void) strcpy( pwname, realuser( pw ) );
- X#else
- X (void) strcpy( pwname, pw->pw_name );
- X#endif
- X
- X /* see if we can use getlogin() to see who it is */
- X (void) strcpy( loginname, (glog=getlogin()) == 0 ? "" : glog );
- X if ( *loginname ) {
- X /* check the passwd file for this guy */
- X pw = getpwnam( loginname );
- X if ( pw ) {
- X ruid = pw->pw_uid;
- X#ifdef DUMBSHORT
- X {
- X struct utmp *ut;
- X if ( strncmp( pwname, loginname, sizeof(ut->ut_name) ) == 0 )
- X (void) strcpy( loginname, pwname );
- X }
- X#endif
- X#ifdef REALUSER
- X (void) strcpy( loginname, realuser( pw ) );
- X#endif
- X }
- X } else {
- X /* no better guess at real identity, use USER if we're root */
- X if ( uid == SU && (glog=getenv("USER"))!=(char *)NULL && *glog ) {
- X /* look up the pw entry for USER */
- X if ( (pw=getpwnam(glog)) != (struct passwd *)NULL ) {
- X ruid = pw->pw_uid;
- X#ifdef REALUSER
- X glog = realuser( pw );
- X#endif
- X }
- X strcpy( loginname, glog );
- X } else
- X strcpy( loginname, pwname );
- X }
- X
- X if (
- X#ifdef REALUSER
- X ! sameuser( pwname, loginname )
- X#else
- X strcmp( pwname, loginname ) != 0
- X#endif
- X && uid != SU ) {
- X /* Names differ, and user isn't SU, so send both */
- X (void) sprintf(sender, "%s(%s)@%s", loginname, pwname, hostname);
- X } else {
- X (void) sprintf(sender, "%s@%s", loginname, hostname);
- X }
- X
- X return( uid == SU );
- X}
- X
- X
- Xprivate int
- Xsendmsg( recipient, message, fromroot )
- Xchar *recipient, *message;
- Xint fromroot;
- X{
- X register char *p, *user, *host;
- X#ifndef REMOTE
- X int local = FALSE;
- X#endif
- X int errcode;
- X if ( (p = index( recipient, '@' )) != CPNULL ) {
- X user = recipient;
- X host = p+1;
- X *p = '\0';
- X } else if ( (p = index( recipient, '!' )) != CPNULL ) {
- X user = p+1;
- X host = recipient;
- X *p = '\0';
- X } else {
- X user = recipient;
- X host = hostname;
- X }
- X/* always go via the daemon, because it means we don't have to be
- X setuid, and it makes things a little bit simpler. I hope - jms.
- X wrong - jms */
- X#ifndef REMOTE
- X /* this only works if they use the full host name, not an alias, but
- X that's okay ... */
- X if ( strcmp( host, hostname ) == 0 )
- X local = TRUE;
- X if ( local )
- X errcode = deliver( sender, user, message, fromroot );
- X else
- X#endif
- X errcode = remote( sender, user, host, message );
- X return( errcode );
- X}
- X
- X
- X
- X/* Warn user on tname if he/she can't receive messages.
- X */
- Xprivate void
- Xreplywarn(tname)
- X char *tname;
- X{
- X struct utmp ut;
- X struct stat sbuf;
- X FILE *fp;
- X char *p;
- X char terminal[80]; /* should be enough ... */
- X
- X if( (fp=fopen( UTMP, "r" )) == FPNULL ) {
- X errmsg( NO_UTMP, hostname, syserr() );
- X } else {
- X if( (p=rindex(tname,'/')) != NULL )
- X tname = p + 1;
- X while ( fread((char*)&ut,sizeof(struct utmp),1,fp) != 0 ){
- X if( strncmp(tname,ut.ut_line,(int)sizeof(ut.ut_line)) == 0 ){
- X (void) sprintf( terminal, "%s%s", DEV, tname );
- X if ( stat(terminal,&sbuf)!=-1 && ((sbuf.st_mode&ALLOW)==0) )
- X errmsg( NO_REPLY, loginname, tname );
- X#ifdef ANSWERBACK
- X answerback( ANS_WARN, loginname, tname );
- X#endif
- X break; /* only need to check the first match */
- X }
- X }
- X (void) fclose( fp );
- X }
- X}
- X
- X
- Xprivate void
- Xusage()
- X{
- X errprintf( "Usage: %s [-l] [-m message] [-p] [-r] [-t] [user ...]",
- X progname );
- X exit( BAD_ARGS );
- X}
- X
- X
- X#ifdef VARARGS
- Xerrprintf( s, va_alist )
- Xchar *s;
- Xva_dcl
- X{
- X va_list ap;
- X (void) fprintf( stderr, "%s: ", progname );
- X va_start( ap );
- X (void) vfprintf( stderr, s, ap );
- X va_end( ap );
- X (void) fputc( '\n', stderr );
- X}
- X
- Xvoid
- Xfatal( s, va_alist )
- Xchar *s;
- Xva_dcl
- X{
- X va_list ap;
- X (void) fprintf( stderr, "%s: ", progname );
- X va_start( ap );
- X (void) vfprintf( stderr, s, ap );
- X va_end( ap );
- X (void) fputc( '\n', stderr );
- X exit( FATAL );
- X}
- X
- X/* VARARGS1 */
- Xerrmsg( msgnum, va_alist )
- Xint msgnum;
- Xva_dcl
- X{
- X va_list ap;
- X (void) fprintf( stderr, "%s: ", progname );
- X va_start( ap );
- X (void) vfprintf( stderr, errmessages[msgnum], ap );
- X va_end( ap );
- X (void) fputc( '\n', stderr );
- X}
- X#else
- X/* VARARGS1 */
- Xerrprintf( a, b, c, d, e, f, g, h, i, j, k )
- Xchar *a;
- X{
- X (void) fprintf( stderr, "%s: ", progname );
- X fprintf( stderr, a, b, c, d, e, f, g, h, i, j, k );
- X (void) fputc( '\n', stderr );
- X}
- X
- X/* VARARGS1 */
- Xvoid
- Xfatal( a, b, c, d, e, f, g, h, i, j, k )
- Xchar *a;
- X{
- X (void) fprintf( stderr, "%s: ", progname );
- X fprintf( stderr, a, b, c, d, e, f, g, h, i, j, k );
- X (void) fputc( '\n', stderr );
- X exit( FATAL );
- X}
- X
- X/* VARARGS1 */
- Xerrmsg( msgnum, a, b, c, d, e )
- Xint msgnum;
- Xchar *a, *b, *c, *d, *e;
- X{
- X errprintf( errmessages[msgnum], a, b, c, d, e );
- X}
- X#endif /* VARARGS */
- X
- Xlist_msgtime()
- X{
- X /*
- X * List time last msg was received.
- X */
- X struct stat statbuf;
- X
- X if (stat(msg_file, &statbuf) == -1)
- X errprintf("can't get date of message file '%s': %s",
- X msg_file, syserr());
- X else
- X printf("last message received %s", ctime(&statbuf.st_mtime));
- X}
- X
- X
- Xlist_msg()
- X{
- X /*
- X * List message to which we are replying.
- X * Just cat the last msg file.
- X */
- X
- X FILE *fp;
- X int c;
- X
- X if ( (fp = fopen(msg_file, "r")) == NULL ) {
- X errprintf("Cannot read last message file '%s'", msg_file );
- X } else {
- X while ( (c = getc(fp)) != EOF ) {
- X putchar(c);
- X }
- X }
- X}
- X
- X
- Xprivate void
- Xgetprevious( buf, size )
- Xchar *buf;
- Xint size;
- X{
- X struct stat sbuf;
- X FILE *pfp;
- X int count;
- X if ( stat( pmsg_file, &sbuf ) == -1 )
- X fatal( "Could not stat previous message file '%s': %s",
- X pmsg_file, syserr() );
- X if ( sbuf.st_uid != ruid )
- X fatal( "You do not own previous message file '%s'", pmsg_file );
- X if ( (pfp = fopen( pmsg_file, "r" )) == (FILE *)NULL )
- X fatal( "Could not fopen previous message file '%s' for read: %s",
- X pmsg_file, syserr() );
- X if ( fgets( buf, size, pfp ) == NULL )
- X fatal( "Could not read previous message from file '%s' (empty?)",
- X pmsg_file );
- X /* In case the file didn't end with a \n, we want to make sure that
- X we don't complain above that it has been truncated. This is kind
- X of gross. */
- X if ( strlen( buf ) < size )
- X strcat( buf, "\n" );
- X (void) fclose( pfp );
- X}
- X
- Xprivate void
- Xputprevious( msg )
- Xchar *msg;
- X{
- X FILE *pfp;
- X if ( (pfp = fopen( pmsg_file, "w" )) == (FILE *)NULL ) {
- X errprintf( "Could not fopen previous message file '%s' for write: %s",
- X pmsg_file, syserr() );
- X } else {
- X fprintf( pfp, "%s\n", msg );
- X fclose( pfp );
- X chown( pmsg_file, ruid, -1 );
- X chmod( pmsg_file, 0600 );
- X }
- X}
- X
- X
- X
- X
- X/*
- X * reply_to - look in MSGFILE to see who sent us
- X * the last message.
- X */
- X
- Xchar *
- Xreply_to()
- X{
- X register char *p;
- X char *index();
- X static char buf[80]; /* Static 'cause we return what's in it. */
- X char userfrom[40], whocares[40], hostfrom[40];
- X FILE *f;
- X
- X if ( (f = fopen(msg_file, "r")) == NULL ) {
- X return( NULL );
- X }
- X
- X if ( fgets(buf, sizeof(buf),f) == NULL )
- X return( NULL );
- X /*
- X * The file can look like
- X * user@host: msg
- X * or
- X * user(somebody)@host: msg
- X * Scan this in a basically cheap way.
- X * I suppose some goofball exceptions could slip through
- X * here if people had () in their login or host name, blah.
- X */
- X
- X
- X if ( (p = index(buf, ':')) == NULL ) {
- X return( NULL ); /* Bad format. */
- X }
- X *p = '\0';
- X
- X /*
- X * Now see which format we have. Strip out intermediate name.
- X * there are probably more rigorous ways to do this
- X */
- X p = index(buf, '(');
- X
- X if ( p != NULL ) {
- X *p++ = '\0'; /* First part is username */
- X p = index(p, ')'); /* Skip middle bit. */
- X if ( p == NULL ) {
- X return(NULL); /* Bad format */
- X }
- X
- X if ( *++p != '@' )
- X return(NULL);
- X
- X strcat(buf, p); /* Tack on hostname. */
- X }
- X
- X return( buf );
- X}
- END_OF_FILE
- if test 12537 -ne `wc -c <'./msg/msg.c'`; then
- echo shar: \"'./msg/msg.c'\" unpacked with wrong size!
- fi
- # end of './msg/msg.c'
- fi
- if test -f './msg/remote.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./msg/remote.c'\"
- else
- echo shar: Extracting \"'./msg/remote.c'\" \(4372 characters\)
- sed "s/^X//" >'./msg/remote.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /source/users/msg/msg/RCS/remote.c,v 1.5 91/08/13 23:59:09 jmsellens Exp $";
- X#endif
- X
- X/* remote.c
- X Deliver a message to a user on a remote machine using TCP/IP.
- X*/
- X
- X#include "msg.h"
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <arpa/inet.h>
- X
- Xchar *syserr();
- X
- Xprivate int sock = -1; /* the socket */
- Xprivate struct sockaddr_in sin;
- X
- X
- Xprivate struct hostent *
- Xfind_host( desthost )
- Xchar *desthost;
- X{
- X /* stolen from finger */
- X static struct hostent def;
- X static struct in_addr defaddr;
- X static char *alist[1];
- X static char namebuf[128];
- X struct hostent *hp;
- X
- X hp = gethostbyname(desthost);
- X if (hp == NULL) {
- X defaddr.s_addr = inet_addr(desthost);
- X if (defaddr.s_addr == -1)
- X return( (struct hostent *)NULL );
- X strcpy(namebuf, desthost);
- X def.h_name = namebuf;
- X#ifdef h_addr
- X /* older things don't have this field. Newer ones #define h_addr */
- X def.h_addr_list = alist;
- X#endif
- X def.h_addr = (char *)&defaddr;
- X def.h_length = sizeof (struct in_addr);
- X def.h_addrtype = AF_INET;
- X def.h_aliases = 0;
- X hp = &def;
- X }
- X return( hp );
- X}
- X
- X
- Xprivate int
- Xstart_remote( desthost )
- Xchar *desthost;
- X{
- X static struct servent *sp = NULL;
- X struct hostent *hp;
- X char buf[BUFSIZ];
- X version ver;
- X int errcode, i;
- X
- X if (sp == NULL)
- X sp = getservbyname( "msg", "tcp" );
- X if (sp == NULL)
- X fatal( "msg/tcp not defined in services file" );
- X hp = find_host( desthost );
- X if (hp == NULL) {
- X errmsg( BAD_HOST, desthost );
- X return( BAD_HOST );
- X }
- X bzero( (char *)&sin, sizeof(sin) );
- X bcopy( hp->h_addr, (char *)&sin.sin_addr, hp->h_length );
- X sin.sin_family = hp->h_addrtype;
- X sin.sin_port = sp->s_port;
- X sock = socket( hp->h_addrtype, SOCK_STREAM, 0 );
- X if (sock < 0)
- X fatal( "couldn't create socket: %s", syserr() );
- X if (connect( sock, (char *)&sin, sizeof(sin) ) < 0) {
- X errmsg( NO_CONNECT, desthost, syserr() );
- X (void) close(sock);
- X sock = -1;
- X return( NO_CONNECT );
- X }
- X /* Now make sure we have a compatible version */
- X ver.v.zero = htonl(0);
- X ver.v.vnum = htonl(VERSION);
- X if ( write( sock, &ver, sizeof(ver) ) < 0 )
- X return( REMOTE_WRITE );
- X errcode = readint( &i );
- X if ( errcode == OK )
- X errcode = i;
- X if ( errcode == VERSION_OK ) {
- X errcode = OK;
- X } else if ( errcode == ERROR_MESSAGE ) {
- X int code = readint( &i );
- X if ( code == OK ) {
- X code = read( sock, buf, i );
- X if ( code == -1 ) {
- X errcode = REMOTE_READ;
- X } else {
- X buf[i] = '\0';
- X errprintf( buf );
- X }
- X } else
- X errcode = code;
- X }
- X return( errcode );
- X}
- X
- X
- Xprivate
- Xstop_remote()
- X{
- X if ( sock >= 0 ) {
- X (void) close( sock );
- X sock = -1;
- X }
- X}
- X
- X
- Xint
- Xremote( sender, user, desthost, message )
- Xchar *sender, *user, *desthost, *message;
- X{
- X char buf[BUFSIZ];
- X int errcode;
- X if ( (errcode = start_remote( desthost )) == OK ) {
- X int writeerr = 0;
- X header h;
- X h.slen = htonl(strlen(sender));
- X h.ulen = htonl(strlen(user));
- X h.mlen = htonl(strlen(message));
- X if ( write( sock, (char *)&h, sizeof(h) ) < 0 ) writeerr++;
- X if ( write( sock, sender, strlen(sender) ) < 0 ) writeerr++;
- X if ( write( sock, user, strlen(user) ) < 0 ) writeerr++;
- X if ( write( sock, message, strlen(message) ) < 0 ) writeerr++;
- X if ( writeerr ) {
- X errcode = REMOTE_WRITE;
- X } else {
- X do {
- X int i;
- X errcode = readint( &i );
- X if ( errcode == OK ) errcode = i;
- X if ( errcode == ERROR_MESSAGE ) {
- X int code = readint( &i );
- X if ( code == OK ) {
- X code = read( sock, buf, i );
- X if ( code == -1 ) {
- X errcode = REMOTE_READ;
- X } else {
- X buf[i] = '\0';
- X errprintf( buf );
- X }
- X } else
- X errcode = code;
- X }
- X } while ( errcode == ERROR_MESSAGE );
- X }
- X }
- X switch ( errcode ) {
- X case REMOTE_READ:
- X case REMOTE_WRITE:
- X errmsg( errcode, desthost, syserr() );
- X break;
- X case NO_ACK:
- X errmsg( errcode, desthost );
- X break;
- X default: /* do nothing - got message back from remote */
- X break;
- X }
- X stop_remote(); /* hope close doesn't change errno */
- X return( errcode );
- X}
- X
- X
- Xint
- Xreadint(np)
- Xint *np;
- X{
- X int n;
- X
- X switch (read(sock, &n, sizeof n)) {
- X case 0:
- X return( NO_ACK );
- X case sizeof(n):
- X *np = ntohl(n);
- X return( OK );
- X case -1:
- X default: /* for incomplete data */
- X return( REMOTE_READ );
- X }
- X /* NOTREACHED */
- X}
- END_OF_FILE
- if test 4372 -ne `wc -c <'./msg/remote.c'`; then
- echo shar: \"'./msg/remote.c'\" unpacked with wrong size!
- fi
- # end of './msg/remote.c'
- fi
- if test ! -d './msgd' ; then
- echo shar: Creating directory \"'./msgd'\"
- mkdir './msgd'
- fi
- if test -f './msgd/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./msgd/Makefile'\"
- else
- echo shar: Extracting \"'./msgd/Makefile'\" \(755 characters\)
- sed "s/^X//" >'./msgd/Makefile' <<'END_OF_FILE'
- XNAME = msgd
- XSERVDIR = /software/users/servers
- XMANDIR = /software/users/man
- XMODE = 555
- X
- XCFLAGS= -DINETD -I../Include
- X
- XOBJECT = msgd.o server.o deliver.o misc.o savemsg.o errtext.o answerback.o
- X
- Xall: $(NAME)
- X
- X$(NAME): $(OBJECT)
- X cc -o $(NAME) $(OBJECT)
- X
- Xinstall: $(NAME)
- X install -s -m $(MODE) $(NAME) $(SERVDIR)/$(NAME)
- X
- Xclean:
- X rm -f a.out core *.o $(NAME)
- X
- X$(OBJECT): ../Include/msg.h ../Include/msgoptions.h
- X
- Xanswerback.o: ../Common/answerback.c
- X cc $(CFLAGS) -c ../Common/answerback.c
- X
- Xdeliver.o: ../Common/deliver.c
- X cc $(CFLAGS) -c ../Common/deliver.c
- X
- Xerrtext.o: ../Common/errtext.c
- X cc $(CFLAGS) -c ../Common/errtext.c
- X
- Xmisc.o: ../Common/misc.c
- X cc $(CFLAGS) -c ../Common/misc.c
- X
- Xsavemsg.o: ../Common/savemsg.c
- X cc $(CFLAGS) -c ../Common/savemsg.c
- END_OF_FILE
- if test 755 -ne `wc -c <'./msgd/Makefile'`; then
- echo shar: \"'./msgd/Makefile'\" unpacked with wrong size!
- fi
- # end of './msgd/Makefile'
- fi
- if test -f './msgd/msgd.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./msgd/msgd.c'\"
- else
- echo shar: Extracting \"'./msgd/msgd.c'\" \(3944 characters\)
- sed "s/^X//" >'./msgd/msgd.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /source/users/msg/msgd/RCS/msgd.c,v 1.3 91/08/14 00:00:14 jmsellens Exp $";
- X#endif
- X
- X#if 0
- X/*
- X * $Log: msgd.c,v $
- X * Revision 1.3 91/08/14 00:00:14 jmsellens
- X * s/eprintf/errprintf/ to avoid libuw clash
- X *
- X * Revision 1.2 90/12/29 22:03:50 jmsellen
- X * VARARGS and logging changes
- X *
- X * Revision 1.1 87/08/06 19:06:38 sahayman
- X * Initial revision
- X *
- X */
- X#endif
- X
- X/* msgd.c
- X msg daemon
- X John Sellens, University of Waterloo
- X*/
- X
- X#include "msg.h"
- X#include <signal.h>
- X
- Xchar *syserr();
- Xextern int errno;
- X
- Xchar *progname;
- Xchar hostname[BUFSIZ];
- Xint client;
- X
- Xmain( argc, argv )
- Xint argc;
- Xchar *argv[];
- X{
- X
- X progname = argv[0];
- X if ( gethostname( hostname, sizeof(hostname) ) )
- X fatal( "Couldn't gethostname(): %s", syserr() );
- X (void) signal( SIGHUP, SIG_IGN );
- X (void) signal( SIGINT, SIG_IGN );
- X (void) signal( SIGALRM, SIG_IGN );
- X (void) signal( SIGTTIN, SIG_IGN );
- X (void) signal( SIGTTOU, SIG_IGN );
- X#ifdef INETD
- X /* Inetd provides the client connection on fd 0. */
- X client = 0;
- X server();
- X exit(0);
- X#else
- X{
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <arpa/inet.h>
- X#include <errno.h>
- X#include <sys/ioctl.h>
- X
- X struct servent *serv;
- X struct sockaddr_in sin;
- X int i, sock;
- X
- X if ( argc != 1 )
- X errprintf( "all arguments ignored" );
- X serv = getservbyname( "msg", "tcp" );
- X if ( serv == (struct servent *)0 )
- X fatal( "msg/tcp not defined in services file" );
- X
- X#ifndef DEBUG
- X /* disconnect from tty */
- X switch ( fork() ) {
- X case 0: /* child */
- X break;
- X case -1:
- X fatal( "couldn't fork (%s), message daemon not started", syserr() );
- X break;
- X default: /* parent */
- X exit( 0 );
- X }
- X for (i = 0; i < 10; i++)
- X close(i);
- X (void) open("/", 0);
- X dup2(0, 1);
- X dup2(0, 2);
- X i = open("/dev/tty", 2);
- X if (i >= 0) {
- X ioctl(i, TIOCNOTTY, (char *)0);
- X close(i);
- X }
- X#endif
- X
- X sin.sin_port = serv->s_port;
- X sock = socket( AF_INET, SOCK_STREAM, 0 );
- X if ( sock == -1 )
- X fatal( "couldn't create socket: %s", syserr() );
- X if ( bind( sock, (caddr_t)&sin, sizeof(sin) ) == -1 )
- X fatal( "couldn't bind socket: %s", syserr() );
- X if ( listen( sock, 5 ) == -1 )
- X fatal( "couldn't listen to socket: %s", syserr() );
- X
- X for ( ;; ) {
- X client = accept(sock, (struct sockaddr *)0, (int *)0);
- X if ( client < 0 ) {
- X if ( errno != EINTR ) {
- X errprintf( "accept: %s", syserr() );
- X sleep(5);
- X }
- X continue;
- X }
- X server();
- X (void) close( client );
- X }
- X /* NOTREACHED */
- X }
- X#endif /* INETD */
- X}
- X
- X#include <syslog.h>
- X
- Xstatic int loglevel = LOG_WARNING;
- X
- Xstatic
- X#ifdef VARARGS
- Xdoerror( s, ap )
- Xchar *s;
- Xva_list ap;
- X#else
- Xdoerror( a, b, c, d, e, f, g, h, i, j, k )
- Xchar *a;
- X#endif
- X{
- X#ifdef DEBUG
- X#ifdef VARARGS
- X vfprintf(stderr, s, ap);
- X#else
- X fprintf(stderr, a, b, c, d, e, f, g, h, i, j, k);
- X#endif
- X putc('\n', stderr); /* syslog will add this */
- X#else
- X static int first = 1;
- X
- X if (first) {
- X#ifdef LOG_DAEMON
- X openlog(progname, LOG_PID, LOG_DAEMON);
- X#else
- X openlog(progname, LOG_PID);
- X#endif
- X first = 0;
- X }
- X#ifdef VARARGS
- X {
- X char buf[BUFSIZ];
- X vsprintf( buf, s, ap );
- X syslog( loglevel, buf );
- X }
- X#else
- X syslog(loglevel, a, b, c, d, e, f, g, h, i, j, k);
- X#endif
- X#endif
- X}
- X
- X/*VARARGS1*/
- X#ifdef VARARGS
- Xerrprintf( s, va_alist )
- Xchar *s;
- Xva_dcl
- X{
- X va_list ap;
- X va_start( ap );
- X doerror( s, ap );
- X va_end( ap );
- X}
- X#else
- Xerrprintf( a, b, c, d, e, f, g, h, i, j, k )
- Xchar *a;
- X{
- X doerror(a, b, c, d, e, f, g, h, i, j, k);
- X}
- X#endif
- X
- X/*VARARGS1*/
- X#ifdef VARARGS
- Xfatal( s, va_alist )
- Xchar *s;
- Xva_dcl
- X{
- X va_list ap;
- X loglevel = LOG_ERR;
- X va_start( ap );
- X doerror( s, ap );
- X va_end( ap );
- X exit( FATAL );
- X}
- X#else
- Xfatal( a, b, c, d, e, f, g, h, i, j, k )
- Xchar *a;
- X{
- X loglevel = LOG_ERR;
- X doerror( a, b, c, d, e, f, g, h, i, j, k );
- X exit( FATAL );
- X}
- X#endif
- END_OF_FILE
- if test 3944 -ne `wc -c <'./msgd/msgd.c'`; then
- echo shar: \"'./msgd/msgd.c'\" unpacked with wrong size!
- fi
- # end of './msgd/msgd.c'
- fi
- if test -f './msgd/server.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./msgd/server.c'\"
- else
- echo shar: Extracting \"'./msgd/server.c'\" \(4063 characters\)
- sed "s/^X//" >'./msgd/server.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *RCSid = "$Header: /source/users/msg/msgd/RCS/server.c,v 1.5 91/08/14 00:00:19 jmsellens Exp $";
- X#endif
- X
- X#if 0
- X/*
- X * $Log: server.c,v $
- X * Revision 1.5 91/08/14 00:00:19 jmsellens
- X * s/eprintf/errprintf/ to avoid libuw clash
- X *
- X * Revision 1.4 90/12/29 22:04:11 jmsellen
- X * VARARGS changes
- X *
- X * Revision 1.3 88/11/07 11:09:54 jmsellens
- X * Call new sanitize() routine to avoid control characters. This is
- X * necessary to avoid someone modifying the msg source and making
- X * their own nasty client that doesn't behave nicely.
- X *
- X * Revision 1.2 88/09/25 02:41:31 jmsellens
- X * Added stuff to accept version records in the future. Taught to
- X * look up the sender's machine name, so that we get the name that
- X * we use to get there, not the value of `hostname` on the remote
- X * machine, which probably isn't properly domain-ized if it's
- X * remote from us.
- X *
- X * Revision 1.1 87/08/06 19:06:43 sahayman
- X * Initial revision
- X *
- X */
- X#endif
- X
- X/* server.c
- X read message coming from server, call deliver, and acknowledge with
- X result code
- X*/
- X
- X/* We ignore any errors communicating with the client, since we figure
- X they just dies or broke out or something */
- X
- X#include "msg.h"
- X#include <netinet/in.h>
- X#include <arpa/inet.h>
- X#include <netdb.h>
- X#include <strings.h>
- X
- Xextern int client;
- Xprivate int remote_ver = 0;
- X
- Xserver()
- X{
- X version ver;
- X header h;
- X int err;
- X char sender[BUFSIZ], user[BUFSIZ], rawmsg[BUFSIZ], message[BUFSIZ];
- X
- X if ( read( client, &ver, sizeof(ver) ) != sizeof(ver) ) goto done;
- X if ( ntohl(ver.v.zero) == 0 ) {
- X /* got a version struct */
- X remote_ver = ntohl(ver.v.vnum);
- X if ( remote_ver > VERSION ) {
- X errmsg( BAD_VERSION, remote_ver, VERSION );
- X goto done;
- X }
- X /* acknowledge that we agree on the version */
- X err = htonl(VERSION_OK);
- X (void) write( client, &err, sizeof(err) );
- X if ( read( client, &h, sizeof(h) ) != sizeof(h) ) goto done;
- X } else {
- X /* Not a version struct, so copy it into header struct */
- X h = ver.h;
- X }
- X h.slen = ntohl(h.slen);
- X h.ulen = ntohl(h.ulen);
- X h.mlen = ntohl(h.mlen);
- X if ( read( client, sender, h.slen ) != h.slen ) goto done;
- X sender[h.slen] = '\0';
- X if ( read( client, user, h.ulen ) != h.ulen ) goto done;
- X user[h.ulen] = '\0';
- X if ( read( client, rawmsg, h.mlen ) != h.mlen ) goto done;
- X rawmsg[h.mlen] = '\0';
- X get_real_sender(sender);
- X sanitize( rawmsg, message );
- X err = deliver( sender, user, message, FALSE );
- X /* deliver gave us a pgrp when it opened a tty... */
- X setpgrp(0, 0);
- X err = htonl(err);
- X (void) write( client, &err, sizeof(err) );
- Xdone:
- X ;
- X}
- X
- X
- X#ifdef VARARGS
- Xerrmsg( msgnum, va_alist )
- Xint msgnum;
- Xva_dcl
- X#else
- Xerrmsg( msgnum, a, b, c, d, e )
- Xint msgnum;
- Xchar *a, *b, *c, *d, *e;
- X#endif
- X{
- X char buf[BUFSIZ];
- X int i = htonl(ERROR_MESSAGE);
- X
- X (void) write( client, &i, sizeof(i) );
- X#ifdef VARARGS
- X {
- X va_list ap;
- X va_start( ap );
- X (void) vsprintf( buf, errmessages[msgnum], ap );
- X va_end( ap );
- X }
- X#else
- X (void) sprintf( buf, errmessages[msgnum], a, b, c, d, e );
- X#endif
- X i = htonl(strlen( buf ));
- X (void) write( client, &i, sizeof(i) );
- X (void) write( client, buf, strlen(buf) );
- X}
- X
- X
- X
- X
- Xget_real_sender( sender )
- Xchar *sender;
- X{
- X struct sockaddr_in from;
- X struct hostent *hp;
- X char *p;
- X int fromlen;
- X fromlen = sizeof(from);
- X
- X p = index( sender, '@' );
- X if ( p == CPNULL ) {
- X errprintf( "sender '%s' contains no '@'", sender );
- X (void) strcat( sender, "@" );
- X p = index( sender, '@' );
- X }
- X p++;
- X if ( index( p, '@' ) != CPNULL ) {
- X errprintf( "sender '%s' contains multiple '@'s", sender );
- X p = rindex( sender, '@' );
- X p++;
- X }
- X if ( getpeername( client, &from, &fromlen ) < 0 ) {
- X errprintf( "couldn't getpeername(): %s", syserr() );
- X (void) strcat( sender, "<unknown>" );
- X } else {
- X hp = gethostbyaddr( (char *)&from.sin_addr, sizeof(struct in_addr),
- X from.sin_family );
- X if ( hp )
- X (void) strcpy( p, hp->h_name );
- X else
- X (void) strcpy( p, inet_ntoa( from.sin_addr ) );
- X }
- X}
- END_OF_FILE
- if test 4063 -ne `wc -c <'./msgd/server.c'`; then
- echo shar: \"'./msgd/server.c'\" unpacked with wrong size!
- fi
- # end of './msgd/server.c'
- fi
- if test -f './services' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'./services'\"
- else
- echo shar: Extracting \"'./services'\" \(40 characters\)
- sed "s/^X//" >'./services' <<'END_OF_FILE'
- Xmsg 1241/tcp # msgd(8) (under inetd)
- END_OF_FILE
- if test 40 -ne `wc -c <'./services'`; then
- echo shar: \"'./services'\" unpacked with wrong size!
- fi
- # end of './services'
- fi
- echo shar: End of shell archive.
- exit 0
-